package list;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyLinkedList<E> {

    private class Node<E> {
        public E element;
        public Node<E> next;

        public Node(E element, Node<E> next) {
            this.element = element;
            this.next = next;
        }

        public Node(E element) {
            this.element = element;
        }

    }

    private Node<E> head;
    private int size;

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    public boolean contains(E obj) {
        return indexOf(obj) != -1;
    }

    public int indexOf(E obj) {
        int currentNodePosition = 0;
        Node<E> currentNode = head;
        while (currentNode != null) {
            if (currentNode.element.equals(obj)) {
                return currentNodePosition;
            }
            currentNode = currentNode.next;
            currentNodePosition++;
        }
        return -1;
    }

    private Node<E> getNodePosition(int pos) {
        int count = 0;
        Node<E> startCount = head;
        while (count < pos) {
            count++;
            startCount = startCount.next;
        }
        return startCount;
    }

    public boolean add(E item) throws IllegalArgumentException {
        if (isEmpty()) {
            addFirst(item);
        } else {
            Node<E> last = getNodePosition(size() - 1);
            last.next = new Node(item);
            size++;
        }
        return true;
    }

    public void addFirst(Object obj) {
        head = new Node(obj, head);
        size++;
    }

    public void removeFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        head = head.next;
    }

    public boolean remove(E obj) {
        int pos = indexOf(obj);
        if (pos != -1) {
            remove(pos);
            return true;
        } else
            throw new NoSuchElementException(
                    "element  you trying to remome does not exist in list");

    }

    public E remove(int pos) {
        if (pos >= size) {
            throw new IllegalArgumentException("There is only " + size
                    + " elements in a list! Index start at 0!");
        }
        E result;
        if (pos == 0) {
            result = head.element;
            head = head.next;
        } else {
            Node<E> previous = getNodePosition(pos - 1);
            result = previous.next.element;
            previous.next = previous.next.next;
        }
        size--;
        return result;
    }

    public void removeAll() {
        Node<E> startCount = head;
        while (startCount != null) {
            startCount.element = null;
            startCount = startCount.next;
            size--;
        }
        head = null;
    }

    public Iterator<E> listIterator() {
        return new SimpleLinkedListIterator();
    }

    private class SimpleLinkedListIterator implements Iterator<E> {

        private Node<E> pointer;
        private Node<E> previous;

        @Override
        public boolean hasNext() {
            if (pointer == null)
                return head != null;
            return pointer.next != null;
        }

        @Override
        public E next() {
            if (!hasNext())
                throw new NoSuchElementException();
            previous = pointer;
            if (pointer == null)
                pointer = head;
            else
                pointer = pointer.next;
            return pointer.element;
        }

        @Override
        public void remove() {
            if (previous == pointer)
                throw new IllegalStateException();

            if (pointer == head) {
                removeFirst();
            } else {
                previous.next = pointer.next;
            }
            pointer = previous;
            size--;
        }

    }
}
